<?php

if(!defined("GC_WEB")) {
	    exit(0);
}


class DB {
	private static $_instance;

	private $_conn;
	private $_config;
	protected function __construct($config) {
		mysqli_report(MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ERROR);

		$this->_config = $config;

		$this->_conn = new mysqli($config['host'], 
						$config['user'], $config['pass'],
						$config['name'], $config['port']);
	}

	public static function getInstance(array $config = array()) {
		if(self::$_instance) {
			return self::$_instance;
		}

		if(empty($config)) {
			throw new Exception(__METHOD__ . " mysql config is empty !");
			return false;
		}

		self::$_instance = new DB($config);
		return self::$_instance;
	}

	public function begin() {
		return $this->_conn->autocommit(false);	
	}

	public function commit() {
		$ret = $this->_conn->commit();
		$this->_conn->autocommit(true);
		return $ret;
	}
	public function rollback() {
		return $this->_conn->rollback();
	}
	public function query($sql, array $binds = array()) {
		$result = array("affected_rows" => 0, "insert_id" => 0, "rows" => array());
		$stmt = $this->_conn->stmt_init();
		$debug = strpos($sql, "gc_config_history") !== false;
		if($stmt->prepare($sql)) {
			$this->_bindParams($stmt, $binds);
			if($stmt->execute()) {
				$stmt->store_result();
				$meta = $stmt->result_metadata();
				//select / desc / show / explain
				if($meta && $fields = $meta->fetch_fields()) {
					$rows = array();
					$row = array();
					$arr = array();
					foreach($fields as $key => $r) {
						$arr[$key] = &$row[$r->name];
					}
					call_user_func_array(array($stmt, "bind_result"), $arr);
					while($stmt->fetch()) {
						$t = array();
						foreach($row as $k => $v) {
							$t[$k] = $v;
						}
						$rows[] = $t;
					}
					$result['affected_rows'] = $stmt->affected_rows;
					$result['rows'] = $rows;
					$meta->close();
				//insert / update / replace / delete
				} else {
					$result['affected_rows'] = $stmt->affected_rows;
					$result['insert_id'] = $stmt->insert_id;
				}
			}
			$stmt->close();
		} else {
			throw new Exception ("prepare $sql failed");
		}
		return $result;
	}

	private function _bindParams($stmt, $binds) {
		$count = count($binds);
		if($stmt && $count > 0) {
			$arr = array();
			array_unshift($binds, str_pad("", $count, "s"));
			foreach($binds as $key => $val) {
				$arr[$key] = &$binds[$key];
			}
			call_user_func_array(array($stmt, "bind_param"), $arr);
		}
	}

	public function quote($str) {
		return mysqli_real_escape_string($this->_conn, $str);
	}

	public function __destruct() {
	}
}
